﻿using System.Collections.Generic;
using System.Xml;
using System.IO;
using System.Text;

namespace HOPETechnik.XMLParser
{
    public interface IXMLStream
    {                
        void OnElement(string strName, Dictionary<string, string> Attribs);
        void OnElementValue(string strName, string strValue);
        void OnElementClosed(string strName);
        XmlTextReader getReader();        
    }

    public abstract class CXMLMemStream : IXMLStream
    {
        protected string m_strXMLFragment;        

        public CXMLMemStream()
        {
            m_strXMLFragment = string.Empty;
        }
        public CXMLMemStream(string strXML)
        {            m_strXMLFragment = strXML;        }

        public virtual void OnElement(string strName, Dictionary<string, string> Attribs) { }
        public virtual void OnElementValue(string strName, string strValue){}
        public virtual void OnElementClosed(string strName){}
        
        public string getResponse()
        {
            return toXML();
        }

        public string toXML()
        {
            //generate XML string
            StringBuilder builder = new StringBuilder();
            XmlWriterSettings setting = new XmlWriterSettings();
            setting.Indent = true;
            setting.Encoding = Encoding.UTF8;
            using (XmlWriter writer = XmlWriter.Create(builder, setting))
            {
                toXML(writer);
            }
            return builder.ToString();
        }
        protected virtual void toXML(XmlWriter writer) { }
        public XmlTextReader getReader()
        { return new XmlTextReader(new StringReader(m_strXMLFragment));}
    };

    public abstract class CXMLFileStream : IXMLStream
    {
        string m_strXMLFilePath;

        public CXMLFileStream(string strPath)
        { m_strXMLFilePath = strPath; }

        public abstract void OnElement(string strName, Dictionary<string, string> Attribs);
        public abstract void OnElementValue(string strName, string strValue);
        public abstract void OnElementClosed(string strName);
        public XmlTextReader getReader()
        { return new XmlTextReader(m_strXMLFilePath); }
    };
    
    public class CXMLParser
    {
        IXMLStream m_XMLStream;        
        Dictionary<string, string> m_attributes=null;        
        
        public CXMLParser()
        {
            m_attributes = new Dictionary<string, string>();            
        }
        public void setXMLStream(IXMLStream stream)
        {
            m_XMLStream = stream;
            m_attributes.Clear();
        }

        public void Parse()
        {
            XmlTextReader reader = m_XMLStream.getReader();
            string strName = string.Empty;
            while (reader.Read())
            {
                switch (reader.NodeType)
                {
                    case XmlNodeType.Element:
                        {
                            strName = reader.Name;
                            m_attributes.Clear();
                            if (reader.HasAttributes)
                            {
                                while (reader.MoveToNextAttribute())
                                {
                                    m_attributes[reader.Name] = reader.Value;
                                }
                            }
                            m_XMLStream.OnElement(strName, m_attributes);
                        }
                        break;

                    case XmlNodeType.Text:  //element value
                        m_XMLStream.OnElementValue(strName, reader.Value);
                        break;

                    case XmlNodeType.EndElement:
                        m_XMLStream.OnElementClosed(strName);
                        strName = string.Empty;
                        break;
                }
            }
            reader.Close();
            m_attributes.Clear();
        }                
    }    

}
